package com.blacksee.bluetoothpoker.logic;

import java.util.Enumeration;
import java.util.Hashtable;
import java.util.Random;
import java.util.Vector;

import com.blacksee.bluetoothpoker.network.BlueNetException;
import com.blacksee.bluetoothpoker.network.NetCommunicator;
import com.blacksee.bluetoothpoker.network.NetworkInterface;
import com.blacksee.bluetoothpoker.network.TableBean;
import com.blacksee.bluetoothpoker.network.messages.AcceptanceResponseMessage;
import com.blacksee.bluetoothpoker.network.messages.CardsMessage;
import com.blacksee.bluetoothpoker.network.messages.ExistingTablesMessage;
import com.blacksee.bluetoothpoker.network.messages.NetMessage;
import com.blacksee.bluetoothpoker.network.messages.PlayerRequestMessage;
import com.blacksee.bluetoothpoker.network.messages.StartGameMessage;
import com.blacksee.bluetoothpoker.ui.PokerCanvas;

public class GameRunner implements Runnable {
	public static final int MENU_STATE = 0;
	public static final int GAME_STATE = 1;
	
	public static final int MAIN_MENU_PAGE = 2;
	public static final int CREATE_GAME_PAGE = 3; 
	public static final int JOIN_GAME_PAGE = 4;  // display the list of available tables
	public static final int ACCEPT_PALYER_PAGE = 5;
	public static final int WAITING_ACCEPTANCE_PAGE = 6; // waiting for confirmation from server that it was accepted
	public static final int WAITING_PLAYERS_PAGE = 7; // server waits the players to join
	public static final int CONFIRMATION_PAGE = 8; //waiting for the game to start
	public static final int RESULT_PAGE = 9;
	public static final int START_GAME_PAGE = 10;
	
	public static final int DEAL_CARDS = 0;
	public static final int BET_ROUND = 1;
	public static final int SHOW_CARDS = 2;
	public static final int TURN_CARDS = 3;
	
	private int state;
	private int menuPage;
	private int gameRound;
	
	private NetworkInterface communicator;
	private PokerCanvas canvas;
	private GameInfo gameInfo;
	private MenuInfo menuInfo;
	
	private Random rand = new Random(System.currentTimeMillis());
	private static String playerName; 

	public GameRunner(PokerCanvas canvas){
		System.out.println("INIT RUNNER");
		playerName = "Player" + rand.nextInt() % 255;
		communicator = NetCommunicator.getInstance();
		communicator.setMyName(playerName);
		this.canvas = canvas; 
		gameInfo = new GameInfo();
		gameInfo.setUser(new PlayerInfo(playerName));
		gameInfo.getUser().setMoney(1000);
		menuInfo = new MenuInfo();
		menuPage = MAIN_MENU_PAGE;
		state = MENU_STATE;
	}
	
	public void run() {
		menu();
		game();
	}
	
	public synchronized void pause(int time) {
      
            try {
                if (time > 0) {
                    wait(time);
                } else {
                    wait();
                }
            } catch (InterruptedException e) {
                //#ifdef DEBUG
                e.printStackTrace();
                //#endif
            }
    }


	private void menu(){
		boolean flag = true;
		canvas.forceRepaint();
		while(flag){
			switch(menuPage){
			case JOIN_GAME_PAGE:{
				System.out.println("waiting for message");
				NetMessage mes = communicator.popMssage();
				if(mes != null && mes instanceof ExistingTablesMessage){
					System.out.println("message received");
					menuInfo.setTables(((ExistingTablesMessage)mes).getTables());
					canvas.forceRepaint();
				}
				break;
			}
			case WAITING_ACCEPTANCE_PAGE:{
				NetMessage mes = communicator.popMssage();
				if(mes != null && mes instanceof AcceptanceResponseMessage){
					menuInfo.setPlayerAccepted(((AcceptanceResponseMessage)mes).isAccepted());
					menuPage = CONFIRMATION_PAGE;
					canvas.forceRepaint();
				}
				break;
			}
			case CONFIRMATION_PAGE:{
				NetMessage mes = communicator.popMssage();
				if (mes != null && mes instanceof  StartGameMessage){
					StartGameMessage objMssg = (StartGameMessage) mes;
					initGameInfo(objMssg.getPlayers(), objMssg.getCards());
					//menuInfo.setPlayersList(objMssg.getPlayers());
					// TODO: may have to change
					/*Enumeration e = players.elements();
					Hashtable allPlayers = new Vector(players.size());
					while (e.hasMoreElements()) {
						allPlayers.addElement(e.nextElement());
					}*/
					//PokerCanvas.instance.postDebugLn("Something");
					state = GAME_STATE;
					flag = false;
					canvas.forceRepaint();
				}	
				break;
			}	
			
			case WAITING_PLAYERS_PAGE:{
				NetMessage mes = communicator.popMssage();
				if(mes != null && mes instanceof PlayerRequestMessage){
					System.out.println("REQUEST RECIEVE");
					PlayerRequestMessage request = (((PlayerRequestMessage)mes));
					try {
						communicator.acceptPlayer(request.getSenderName(), request.getSenderID());
						System.out.println(request.getSenderID() + " " + request.getSenderName());
						menuInfo.addPlayer(request.getSenderID(), request.getSenderName());
						
						canvas.forceRepaint();
					} catch (BlueNetException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}catch (Exception  e){
						e.printStackTrace();
					}				
				}
				break;
			}

			case START_GAME_PAGE:{
				NetMessage mes = communicator.popMssage();
				if (mes != null && mes instanceof  StartGameMessage){
					System.out.println("RECEIVE START MESSAGE");
					StartGameMessage objMssg = (StartGameMessage) mes;
					initGameInfo(objMssg.getPlayers(), objMssg.getCards());
					//menuInfo.setPlayersList(objMssg.getPlayers());
					state = GAME_STATE;
					flag = false;
					canvas.forceRepaint();
				}	
				break;
			}
			}
			pause(200);
		}
	}
	
	private void game(){
		gameRound = DEAL_CARDS;
		while(true){
			switch(gameRound){
				case DEAL_CARDS:{
					NetMessage mes = communicator.popMssage();
					if(mes != null && mes instanceof CardsMessage){
						String cards = ((CardsMessage)mes).getCards();
						Card first = new Card(cards.charAt(0), cards.charAt(1));
						Card second = new Card(cards.charAt(2), cards.charAt(3));
						gameInfo.getUser().setCards(new Card[]{first, second});
					}
				}
				case BET_ROUND:{
					
				}
				case  SHOW_CARDS:{
				
				
				}
			}
		}
	}
	
	public void initGameInfo(Hashtable players, Vector cards){
		Enumeration playerNames = players.elements();
		int i = 0;
		while(playerNames.hasMoreElements()){
			PlayerInfo player = new PlayerInfo((String)playerNames.nextElement());
			player.setOrderNumber(i);
			player.setCards(new Card[]{(Card)cards.elementAt(0), (Card)cards.elementAt(1)});
			if(player.getName().equals(playerName)){
				gameInfo.setUser(player);
			}else{
				gameInfo.addPlayer(player);
			}
			i++;
		}
		gameInfo.setPlayerInTurn(0);
	}
	public void setState(int state, int subState){
		switch(state){
			case MENU_STATE : {
				menuPage = subState;
			}
			case GAME_STATE : {
				
			}
		}
		this.state = state;
	}
	
	public int getState(){
		return state;
	}
	
	public int getMenuPage(){
		return menuPage;
	}
	
	public void raise(int amount){
	
	}
	
	public void check(){
		
	}
	
	public void fold(){
	
	}
	
	public void call(){
		
	}
	
	public void createGame(String name){
		menuPage = WAITING_PLAYERS_PAGE;
		communicator.createGame(name);
		canvas.forceRepaint();
	}
	
	public void acceptPlayer(String name){
		gameInfo.addPlayer(new PlayerInfo(name)); 
	}
	
	public void joinGame(int tableID){
		menuPage = WAITING_ACCEPTANCE_PAGE;
		try {
			communicator.joinGame((TableBean)menuInfo.getTableBeans().elementAt(tableID));
		} catch (BlueNetException e) {
			// TODO Handle network exception
			e.printStackTrace();
		}
		canvas.forceRepaint();
	}
	
	public void selectCreateGameOption(){
		menuPage = CREATE_GAME_PAGE;
		canvas.forceRepaint();
	}
	
	public void selectJoinGameOption(){
		menuPage = JOIN_GAME_PAGE;
		
		communicator.findTables();
		
		canvas.forceRepaint();
	}
	
	public void startGame(){
		try {
			communicator.startGame(menuInfo.getPlayersList());
		} catch (BlueNetException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		menuPage = START_GAME_PAGE;
		
	}
	
	public void backToMainMenu(){
		
	}
	
	public GameInfo getGameInfo(){
		return gameInfo;
	}
	
	public MenuInfo getMenuInfo(){
		return menuInfo;
	}
	
	
}
